<?php

declare(strict_types=1);

namespace App\Middleware;

use Hyperf\Context\Context;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;

/**
 * 跨域-中间件
 */
class CrossDomainMiddleware implements MiddlewareInterface
{
        /**
         * 处理过程
         * @param ServerRequestInterface $request
         * @param RequestHandlerInterface $handler
         * @return ResponseInterface
         */
        public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
        {
                if (strtolower($request->getMethod()) === 'options') {
                        $response = Context::get(ResponseInterface::class);
                        return $this->configCrossDomainResponse($request, $response);
                }
                $request = $request->withAttribute('timestamp', time());
                $response = $handler->handle($request);
                if ($request->getHeader('origin') || strtolower($request->getMethod()) === 'options') {
                        $response = $this->configCrossDomainResponse($request, $response);
                }
                return $response;
        }

        /**
         * 配置跨域响应
         * @param ServerRequestInterface $request
         * @param ResponseInterface $response
         * @return ResponseInterface
         */
        private function configCrossDomainResponse(ServerRequestInterface $request, ResponseInterface $response): ResponseInterface
        {
                return $response
                        ->withHeader('Content-Type', $request->getHeader('content-type')[0] ?? 'application/json;charset=utf-8')
                        ->withHeader('Access-Control-Allow-Origin', $request->getHeader('origin')[0] ?? '*')
                        ->withHeader('Access-Control-Allow-Credentials', 'true')
                        ->withHeader('Access-Control-Allow-Headers', ACCESS_CONTROL_ALLOW_HEADERS)
                        ->withHeader('Access-Control-Allow-Methods', ACCESS_CONTROL_ALLOW_METHODS);
        }
}
